package org.jim.server.command.handler;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.StringUtils;
import org.jim.core.ImChannelContext;
import org.jim.core.ImPacket;
import org.jim.core.ImStatus;
import org.jim.core.config.ImConfig;
import org.jim.core.exception.BimException;
import org.jim.core.exception.ImException;
import org.jim.core.message.MessageHelper;
import org.jim.core.packets.*;
import org.jim.core.utils.JsonKit;
import org.jim.server.JimServerAPI;
import org.jim.server.command.AbstractCmdHandler;
import org.jim.server.config.ImServerConfig;
import org.jim.server.processor.friend.FriendCmdProcessor;
import org.jim.server.protocol.ProtocolManager;
import org.jim.server.util.ImServerKit;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 添加好友请求信息
 */
public class FriendReqHandler extends AbstractCmdHandler {

    @Override
    public ImPacket handler(ImPacket packet, ImChannelContext channelContext) throws ImException {
        if (packet.getBody() == null) {
            return ProtocolManager.Packet.dataInCorrect(Command.COMMAND_FRIEND_RESP, ImStatus.C10022, channelContext);
        }
        FriendReqBody reqBody = JsonKit.toBean(packet.getBody(), FriendReqBody.class);
        if (reqBody == null || StringUtils.isBlank(reqBody.getFriendId()) || Objects.isNull(OperatorType.forNumber(reqBody.getType()))
                || Arrays.stream(FriendType.values()).noneMatch(m -> m.name().equalsIgnoreCase(reqBody.getFriendType()))) {
            return ProtocolManager.Packet.dataInCorrect(Command.COMMAND_FRIEND_RESP, ImStatus.C10022, channelContext);
        }
        User user = ImServerKit.getUser(channelContext);
        boolean hasUserInfo = Objects.nonNull(user);
        if (!hasUserInfo && StringUtils.isBlank(reqBody.getUserId())) {
            return ProtocolManager.Packet.dataInCorrect(Command.COMMAND_FRIEND_RESP, ImStatus.C10022, channelContext);
        }
        String userId = hasUserInfo ? user.getUserId() : reqBody.getUserId();
        String friendId = reqBody.getFriendId();
        String ft = reqBody.getFriendType();
        RespBody resPacket = new RespBody(Command.COMMAND_FRIEND_RESP, ImStatus.C10000);
        resPacket.setData(JSON.toJSONString(ImmutableMap.of("type", reqBody.getType())));
        OperatorType operatorType = OperatorType.forNumber(reqBody.getType());
        FriendCmdProcessor singleProcessor = getSingleProcessor(FriendCmdProcessor.class);
        switch (Objects.requireNonNull(operatorType)) {
            case ADD:
                try {
                    User friend = singleProcessor.preCheck(userId, friendId, ft);
                    //如果是客服类型，直接添加好友
                    if (FriendType.customer.name().equalsIgnoreCase(ft)) {
                        singleProcessor.addCustomerFriend(userId, friendId);
                        if (hasUserInfo) {
                            List<User> users = user.getFriends().get(0).getUsers();
                            if (users.stream().noneMatch(m -> m.getUserId().equalsIgnoreCase(friendId))) {
                                users.add(friend);
                            }
                            JimServerAPI.bindUser(channelContext, userId);
                        }
                    } else {
                        ImServerConfig imServerConfig = ImConfig.Global.get();
                        MessageHelper messageHelper = imServerConfig.getMessageHelper();
                        ApplyFriendDO applyFriendDO = new ApplyFriendDO();
                        applyFriendDO.setStatus(0);
                        applyFriendDO.setTimestamp(System.currentTimeMillis());
                        applyFriendDO.setTo(friendId);
                        applyFriendDO.setToNick(friend.getNick());
                        applyFriendDO.setToAvatar(friend.getAvatar());
                        applyFriendDO.setFrom(userId);
                        if (hasUserInfo) {
                            applyFriendDO.setFromNick(user.getNick());
                            applyFriendDO.setFromAvatar(user.getAvatar());
                        } else {
                            applyFriendDO.setFromNick(userId);
                        }
                        //记录好友申请记录
                        messageHelper.recodeApplyFriend(userId, applyFriendDO);
                        ImPacket chatPacket = new ImPacket(Command.COMMAND_FRIEND_REQ, new RespBody(Command.COMMAND_FRIEND_REQ, applyFriendDO).toByte());
                        chatPacket.setSynSeq(packet.getSynSeq());
                        JimServerAPI.sendToUser(friendId, chatPacket);
                    }
                } catch (BimException e) {
                    return ProtocolManager.Packet.dataInCorrect(Command.COMMAND_FRIEND_RESP, e.getImStatus(), channelContext);
                }
                break;
            case DEL:
                singleProcessor.delFriend(userId, friendId);
                if (hasUserInfo) {
                    List<User> users = user.getFriends().get(0).getUsers();
                    users.removeIf(f -> f.getUserId().equals(friendId));
                    JimServerAPI.bindUser(channelContext, userId);
                }
                break;
            case BLACK:
                singleProcessor.addBlack(userId, friendId);
                if (hasUserInfo) {
                    List<User> users = user.getFriends().get(0).getUsers();
                    users.removeIf(f -> f.getUserId().equals(friendId));
                    JimServerAPI.bindUser(channelContext, userId);
                }
                break;
            case REMOVE:
                singleProcessor.removeBlack(userId, friendId);
                break;
            case NICKNAME:
                String friendName = reqBody.getFriendName();
                if (StringUtils.isBlank(friendName)) {
                    singleProcessor.resetFriendNickname(userId, friendId);
                } else {
                    singleProcessor.setFriendNickname(userId, friendId, friendName);
                }
                break;
            default:
                break;
        }
        return ProtocolManager.Converter.respPacket(resPacket, channelContext);
    }

    @Override
    public Command command() {
        return Command.COMMAND_FRIEND_REQ;
    }
}
